﻿using DynamicData;
using Force.DeepCloner;
using Shinva.Variables.Interface;
using Shinva.Variables.Models;
using Shinva.Variables.Type.combination;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Documents;
using System.Windows.Media;
using Unity.Events;

namespace Shinva.Variables.Helper
{
    public class CodeGenerator
    {  //这是整个C代码的数据
        private readonly StringBuilder _sb = new StringBuilder();

        private readonly StringBuilder _sb_external = new StringBuilder();

        private readonly Dictionary<string, int> _structCounter = new Dictionary<string, int>();
        private  PlcVariableTable _table;
        private readonly HashSet<string> _customTypes = new HashSet<string>();
        private int indentLevel { get; set; } = 0; // 缩进级别

        private static readonly Dictionary<string, string> TypeMapping = new Dictionary<string, string>
        {
            {"Int", "int32_t"},
            {"UInt", "uint32_t"},
            {"Float", "float"},
            {"Double", "double"},
            {"Bool", "uint8_t"},
            {"String", "char[32]"},
            {"Struct", "struct"} // 特殊处理结构体类型
        };

        public CodeGenerator()
        {
           
            //GenerateExternalDeclaration();
            var test = _sb_external.ToString();
            //CollectCustomTypes(_table);
        }

        public string GenerateCode(PlcVariableTable root)
        {
            try
            {
                _table = root.DeepClone();
                _sb.Clear();
                _sb_external.Clear();
                ProcessTable(_table);
                _sb.Insert(0, _sb_external.ToString());
                AddFileHeader();
                //ValidateCustomTypes();
                return _sb.ToString();
            }
            catch (Exception ex)
            {
                throw new CodeGenerationException("代码生成失败", ex);
            }
        }

        private void AddFileHeader()
        {

            _sb.Insert(0, "/*****************内嵌结构体的定义*****************/\n");
            _sb.Insert(0, "\n");
            _sb.Insert(0, "#include <stdint.h>\n");
            _sb.Insert(0, "#pragma once\n");
            _sb.Insert(0, "\n");
            _sb.Insert(0, "/********************************************/\n");
            _sb.Insert(0, " /* 自动生成的变量结构体定义*/\n");
            _sb.Insert(0, " /* 请勿手动修改此文件*/\n");
            _sb.Insert(0, " /********************************************/\n");

        }

        private void ProcessTable(PlcVariableTable table)
        {
            //最外层结构体，变量表的结构体
            _sb.AppendLine();
            _sb.AppendLine($"/*****************变量表结构体*************************/");
            _sb.AppendLine($"// 变量表结构体");
            _sb.AppendLine($"typedef struct {table.Name}");
            _sb.AppendLine("{");
            indentLevel++;
            foreach (var item in table.GetMembers())
            {
                if (item is PlcStruct ps)
                {
                    //AddNewLine(_sb, indentLevel, $"/**{ps.FullName}**/");
                    //AddNewLine(_sb, indentLevel, $"struct ");
                    //AddNewLine(_sb, indentLevel, "{");
                    //indentLevel++;
                    //AddNewLine(_sb, 0, GenerateStructDeclaration(ps,indentLevel));
                    //indentLevel--;
                    //AddNewLine(_sb, indentLevel, $"}} {ps.Symbol}_t;");
                    AddNewLine(_sb, indentLevel, $"{ps.Symbol}_s {ps.Symbol};");
                    GenerateExternalDeclaration(ps);
                    //AddNewLine(_sb, 0, GenerateStructDeclaration(ps, indentLevel));
                }
                else if (item is PlcArray pa)
                {
                    AddNewLine(_sb, 0, GenerateArrayDeclaration(pa, indentLevel));
                }
                else
                {
                    AddNewLine(_sb, indentLevel, $"{item.DataType} {item.Symbol} ;");
                }
            }
            indentLevel--;
            _sb.AppendLine($"\n}} {table.Name}_s;");
        }
        /// <summary>
        /// 添加新行
        /// </summary>
        /// <param name="sb">字符串</param>
        /// <param name="indentCount">新一行的缩进值</param>
        /// <param name="content">新一行内容</param>
        static void AddNewLine(StringBuilder sb, int indentCount, string content)
        {
            if (sb.Length > 0)
            {
                sb.AppendLine();

            }
            string indent = new string(' ', indentCount * 4); // 假设每个缩进是 4 个空格
            sb.Append(indent);
            sb.Append(content);
            //sb.AppendLine();
        }


        private string GenerateStructDeclaration(PlcStruct node, int indentLevel)
        {
            StringBuilder stringBuilder = new StringBuilder();
            var structName = node.Name;
            //AddNewLine(stringBuilder, indentLevel, $"/**{node.Symbol}**/");
            //AddNewLine(stringBuilder, indentLevel, $"typedef struct {node.Name}");
            //AddNewLine(stringBuilder, indentLevel, "{");
            //indentLevel++;
            foreach (var item in node.GetMembers())
            {
                if (item is PlcStruct ps)
                {
                    AddNewLine(stringBuilder, indentLevel, $"{ps.Symbol}_s {ps.Symbol};");
                    GenerateExternalDeclaration(ps);
                }
                else if (item is PlcArray pa)
                {

                    AddNewLine(stringBuilder, 0, GenerateArrayDeclaration(pa, indentLevel));
                }
                else
                {
                    AddNewLine(stringBuilder, indentLevel, $"{item.DataType} {item.Symbol};");
                }


            }
            //indentLevel--;
            //AddNewLine(stringBuilder, indentLevel, $"}} {node.Name}_t;");
            return stringBuilder.ToString();
        }
        private string GenerateArrayDeclaration(PlcArray node, int indentLevel)
        {
            StringBuilder stringBuilder = new StringBuilder();
            if (node.MemberDataType == DataType.Struct)
            {
                AddNewLine(stringBuilder, indentLevel, $"/**{node.FullName}**/");
                AddNewLine(stringBuilder, indentLevel, $" {node.Symbol}_s {node.Symbol} [{node.Length}];");
                GenerateExternalDeclaration((PlcStruct)node.GetMembers()[0]);
            }
            else
            {
                AddNewLine(stringBuilder, indentLevel, $"{node.MemberDataType} {node.Symbol}[{node.Length}];");
            }
            return stringBuilder.ToString();
        }
        private string GenerateMemberDeclaration(IPlcMember node)
        {
            var typeName = node.DataType.ToString();
            var arraySuffix = node.SizeInBytes();
            return $"{typeName}{arraySuffix} {SanitizeName(node.Name)} ;";
        }

        //如果结构体或者数组中包含额外的结构体，
        //那么直接在变量表外部声明这个额外的结构体，
        //以保证该结构体的可复用性
        private void GenerateExternalDeclaration(PlcStruct ps)
        {
            int indent_t = 0;
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine($"typedef struct ");
            stringBuilder.AppendLine("{");
            AddNewLine(stringBuilder, 0, GenerateStructDeclaration(ps, indent_t));
            indent_t--;
            if (ps.Parent.DataType == DataType.Array)
            {

                stringBuilder.AppendLine($"\n}} {ps.Parent.Symbol}_s;");
            }
            else
            {
                stringBuilder.AppendLine($"\n}} {ps.Symbol}_s;");
            }
            //_sb_external.Insert(0, stringBuilder.ToString());
            _sb_external.AppendLine(stringBuilder.ToString());
        }

        private string GetTypeIdentifier(IPlcMember node)
        {
            if (node is PlcStruct ps)
            {
                // 结构体引用需要带struct前缀
                return $"struct {GetUniqueStructName(ps.Name)}";
            }

            // 处理基础类型和自定义类型
            return TypeMapping.TryGetValue(node.DataType.ToString(), out var mappedType)
                ? mappedType
                : $"{SanitizeName(node.DataType.ToString())}_t";
        }



        private string GetUniqueStructName(string baseName)
        {
            var sanitized = SanitizeName(baseName);
            if (!_structCounter.ContainsKey(sanitized))
            {
                _structCounter[sanitized] = 0;
                return sanitized;
            }

            _structCounter[sanitized]++;
            return $"{sanitized}_{_structCounter[sanitized]}";
        }



        private void ValidateCustomTypes()
        {
            foreach (var type in _customTypes)
            {
                if (!_structCounter.ContainsKey(type))
                {
                    throw new CodeGenerationException(
                        $"检测到未定义的自定义类型: {type}", null);
                }
            }
        }

        private string SanitizeName(string input)
        {
            var sb = new StringBuilder();
            foreach (char c in input)
            {
                sb.Append(char.IsLetterOrDigit(c) ? c : '_');
            }
            return sb.ToString().TrimStart('_');
        }

        private string MapType(string type)
        {
            if (TypeMapping.TryGetValue(type, out var mapped))
            {
                return mapped;
            }

            // 自定义类型直接返回
            return type;
        }
    }

    public class CodeGenerationException : Exception
    {
        public CodeGenerationException(string message, Exception inner)
            : base(message, inner) { }
    }
}
